#include "game.h"
#include "ui_game.h"

game::game(QWidget *parent,int level) :
    QWidget(parent),
    ui(new Ui::game)
{
    this->level=level;
    condition=0;
    switch(level){
    case 1:
        MAX_STEP=10;
        break;
    case 2:
        MAX_STEP=50;
        break;
    case 3:
       MAX_STEP=65;
        break;
    case 4:
        MAX_STEP=30;
        break;
    }
    ui->setupUi(this);
    setFocus();
    initmap();
    connect(this, SIGNAL(change()), this, SLOT(update()));
    connect(this, SIGNAL(gameover()), this, SLOT(gameOverControl()));
    connect(this, SIGNAL(gamesuccess()), this, SLOT(gameSuccessControl()));
    initmap();
    emit change();
}

game::~game()
{
    delete ui;
}
void game::initmap(){
    this->resize(SCREEN_WIDTH, SCREEN_HEIGHT); // 初始化屏幕高度宽度
    setWindowIconText(QString("抽象的推箱子"));
    step = 0;
    pre_pos.p = NUL;
    //复制对应关卡的map到map_copy

        for (int i = 0; i < LINE; i++) {
            for (int j = 0; j < COLUMN; j++) {
                map_copy[i][j]=map[level-1][i][j];
            }
        }
    ji=0;
    condition=0;
}
void game::init(){
    for (int i = 0; i < LINE; i++) {
        for (int j = 0; j < COLUMN; j++) {
            map_copy[i][j]=map[level-1][i][j];
        }
    }
    step = 0;
    ji=0;
    condition=0;
    update();
    pre_pos.p = NUL;
    over=0;
    emit change();
}
//游戏控制
void game::gameControl(enum Direction direction) {
    if (direction == UP) { // 上方向
        dir=1;
        if (map_copy[man.x - 1][man.y] == FLOOR && pre_pos.p == NUL) { // 上方向为地板且脚下不是目的地
            changeMap(man.x, man.y, FLOOR); // 原位置换为地板
            changeMap(man.x - 1, man.y, MAN); // 上方向位置换为人
            step++; // 步数++
        } else if (map_copy[man.x - 1][man.y] == BOX &&map_copy[man.x - 2][man.y] == FLOOR && pre_pos.p == NUL) { // 上方向为箱子，箱子上方向为地板， 且脚下不为目的地
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x - 1, man.y, MAN);
            changeMap(man.x - 2, man.y, BOX);
            step++;
        } else if (map_copy[man.x - 1][man.y] == BOX && map_copy[man.x - 2][man.y] == DES) { // 上方向为箱子，箱子上方向为目的地
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x - 1, man.y, MAN);
            changeMap(man.x - 2, man.y, HIT);
            step++;
        } else if (map_copy[man.x - 1][man.y] == DES) { // 上方向为目的地
            changeMap(man.x - 1, man.y, MAN);
            changeMap(man.x, man.y, FLOOR);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x - 1][man.y] == FLOOR && pre_pos.p == DES) { // 上方向为地板且脚下为目的地
            pre_pos.p = NUL;
            changeMap(man.x, man.y, DES);
            changeMap(man.x - 1, man.y, MAN);
            step++;
        } else if (map_copy[man.x - 1][man.y] == HIT && map_copy[man.x - 2][man.y] == FLOOR) { // 上方向为目的地且目的地上方为地板
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x - 1, man.y, MAN);
            changeMap(man.x - 2, man.y, BOX);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x - 1][man.y] == BOX && map_copy[man.x - 2][man.y] == FLOOR && pre_pos.p == DES) { // 上方向为箱子，且箱子上方为地板且脚下为目的地
            changeMap(man.x, man.y, DES);
            changeMap(man.x - 1, man.y, MAN);
            changeMap(man.x - 2, man.y, BOX);
            pre_pos.p = NUL;
            step++;
        }
    } else if (direction == DOWN) {
        dir=3;
        if (map_copy[man.x + 1][man.y] == FLOOR && pre_pos.p == NUL) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x + 1, man.y, MAN);
            step++;
        } else if (map_copy[man.x + 1][man.y] == BOX && map_copy[man.x + 2][man.y] == FLOOR && pre_pos.p == NUL) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x + 1, man.y, MAN);
            changeMap(man.x + 2, man.y, BOX);
            step++;
        } else if (map_copy[man.x + 1][man.y] == BOX && map_copy[man.x + 2][man.y] == DES) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x + 1, man.y, MAN);
            changeMap(man.x + 2, man.y, HIT);
            step++;
        } else if (map_copy[man.x + 1][man.y] == DES) {
            changeMap(man.x + 1, man.y, MAN);
            changeMap(man.x, man.y, FLOOR);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x + 1][man.y] == FLOOR && pre_pos.p == DES) {
            pre_pos.p = NUL;
            changeMap(man.x, man.y, DES);
            changeMap(man.x + 1, man.y, MAN);
            step++;
        } else if (map_copy[man.x + 1][man.y] == HIT &&map_copy[man.x + 2][man.y] == FLOOR) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x + 1, man.y, MAN);
            changeMap(man.x + 2, man.y, BOX);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x + 1][man.y] == BOX && map_copy[man.x + 2][man.y] == FLOOR && pre_pos.p == DES) {
            changeMap(man.x, man.y, DES);
            changeMap(man.x + 1, man.y, MAN);
            changeMap(man.x + 2, man.y, BOX);
            pre_pos.p = NUL;
            step++;
        }
    } else if (direction == LEFT) {
        dir=4;
        if (map_copy[man.x][man.y - 1] == FLOOR && pre_pos.p == NUL) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y - 1, MAN);
            step++;
        } else if (map_copy[man.x][man.y - 1] == BOX && map_copy[man.x][man.y - 2] == FLOOR && pre_pos.p == NUL) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y - 1, MAN);
            changeMap(man.x, man.y - 2, BOX);
            step++;
        } else if (map_copy[man.x][man.y - 1] == BOX && map_copy[man.x][man.y - 2] == DES) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y - 1, MAN);
            changeMap(man.x, man.y - 2, HIT);
            step++;
        } else if (map_copy[man.x][man.y - 1] == DES) {
            changeMap(man.x, man.y - 1, MAN);
            changeMap(man.x, man.y, FLOOR);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x][man.y - 1] == FLOOR && pre_pos.p == DES) {
            pre_pos.p = NUL;
            changeMap(man.x, man.y, DES);
            changeMap(man.x, man.y - 1, MAN);
            step++;
        } else if (map_copy[man.x][man.y - 1] == HIT && map_copy[man.x][man.y - 2] == FLOOR) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y - 1, MAN);
            changeMap(man.x, man.y - 2, BOX);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x][man.y - 1] == BOX && map_copy[man.x][man.y - 2] == FLOOR && pre_pos.p == DES) {
            changeMap(man.x, man.y, DES);
            changeMap(man.x, man.y - 1, MAN);
            changeMap(man.x, man.y - 2, BOX);
            pre_pos.p = NUL;
            step++;
        }
    } else if (direction == RIGHT) {
        dir=2;
        if (map_copy[man.x][man.y + 1] == FLOOR && pre_pos.p == NUL) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y + 1, MAN);
            step++;
        } else if (map_copy[man.x][man.y + 1] == BOX &&map_copy[man.x][man.y + 2] == FLOOR && pre_pos.p == NUL){
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y + 1, MAN);
            changeMap(man.x, man.y + 2, BOX);
            step++;
        } else if (map_copy[man.x][man.y + 1] == BOX && map_copy[man.x][man.y + 2] == DES) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y + 1, MAN);
            changeMap(man.x, man.y + 2, HIT);
            step++;
        } else if (map_copy[man.x][man.y + 1] == DES) {
            changeMap(man.x, man.y + 1, MAN);
            changeMap(man.x, man.y, FLOOR);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x][man.y + 1] == FLOOR && pre_pos.p == DES) {
            pre_pos.p = NUL;
            changeMap(man.x, man.y, DES);
            changeMap(man.x, man.y + 1, MAN);
            step++;
        } else if (map_copy[man.x][man.y + 1] == HIT && map_copy[man.x][man.y + 2] == FLOOR) {
            changeMap(man.x, man.y, FLOOR);
            changeMap(man.x, man.y + 1, MAN);
            changeMap(man.x, man.y + 2, BOX);
            pre_pos.p = DES;
            step++;
        } else if (map_copy[man.x][man.y + 1] == BOX && map_copy[man.x][man.y + 2] == FLOOR && pre_pos.p == DES) {
            changeMap(man.x, man.y, DES);
            changeMap(man.x, man.y + 1, MAN);
            changeMap(man.x, man.y + 2, BOX);
            pre_pos.p = NUL;
            step++;
        }
    }else if(direction == ATTACK){

       changeMap(man.x, man.y, atk);
   repaint();
        Sleep(200);
        changeMap(man.x,man.y,MAN);
   repaint();
        switch(dir){
        case 4:
            if(man.y-1<0) break;
            changeMap(man.x, man.y-1, hand);
               repaint();
              Sleep(200);
            changeMap(man.x, man.y -1, FLOOR);
               repaint();
            break;
         case 3:
            if(man.x+1>=LINE) break;
            changeMap(man.x+1, man.y, hand);
            repaint();
                  Sleep(200);

            changeMap(man.x+1, man.y, FLOOR);
              repaint();
            break;
        case 1:
           if(man.x-1<0) break;
          changeMap(man.x-1, man.y, hand);
             repaint();
          Sleep(200);

          changeMap(man.x-1, man.y, FLOOR);
          repaint();
           break;
        case 2:
           if(man.y+1>=COLUMN) break;
             changeMap(man.x, man.y+1, hand);
               repaint();
             Sleep(200);
           changeMap(man.x, man.y+1, FLOOR);
              repaint();
            break;
        }
    }
}
bool game::isOver() {
    for (int i = 0; i < LINE; i++) {
        for (int j = 0; j < COLUMN; j++) {
            if (map_copy[i][j] == DES) return false;
        }
    }
    for (int i = 0; i < LINE; i++) {
        for (int j = 0; j < COLUMN; j++) {
            if (map_copy[i][j] == BOX) return false;
        }
    }
    return true;
}
void game::changeMap(int line, int column, enum Map m) {
    map_copy[line][column] = m;
    emit change();
}
//绘图事件
void game::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    QFont font("黑体", 30, QFont::ExtraLight, false);
    QPen pen;
    pen.setColor(Qt::white);
    painter.setPen(pen);
    painter.setFont(font);
    painter.drawPixmap(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, QPixmap(BLACKGROUND_PATH)); // 绘制背景
    switch(condition){
    case 0://乐
        painter.drawPixmap(0, SCREEN_HEIGHT-150, 150, 150, QPixmap(MAN_PATH)); // 绘制状态
        painter.drawText(200,SCREEN_HEIGHT-75 , QString("当前状态：乐"));//状态显示
        emit change();
        break;
    case 1://绷
        painter.drawPixmap(0, SCREEN_HEIGHT-150, 150, 150, QPixmap(BENG)); // 绘制状态
        painter.drawText(200,SCREEN_HEIGHT-75 , QString("当前状态：绷"));//状态显示
                emit change();
        break;
    case 2://急
        painter.drawPixmap(0, SCREEN_HEIGHT-150, 150, 150, QPixmap(JI)); // 绘制状态
        painter.drawText(200,SCREEN_HEIGHT-75 , QString("当前状态：急"));//状态显示
                emit change();
        break;
    case 3://赢
        painter.drawPixmap(0, SCREEN_HEIGHT-150, 150, 150, QPixmap(MAN_WIN)); // 绘制状态
        painter.drawText(200,SCREEN_HEIGHT-75 , QString("当前状态：赢"));//状态显示
                emit change();
        break;
    case 4://寄
        painter.drawPixmap(0, SCREEN_HEIGHT-150, 150, 150, QPixmap(MAN_LOSE)); // 绘制状态
        painter.drawText(200,SCREEN_HEIGHT-75 , QString("当前状态：寄"));//状态显示
        emit change();
        break;
    }
    if(chouxiang){
        painter.drawText(600,SCREEN_HEIGHT-75 , QString("抽象模式：开"));
        update();
    }else{
         painter.drawText(600,SCREEN_HEIGHT-75 , QString("抽象模式：关"));
         update();
    }

    painter.drawText(40, 40, QString("步数：%1").arg(step));//显示计步器
    painter.drawText(600, 40, QString("步数限制：%1").arg(MAX_STEP));
    for (int i = 0; i < LINE; i++) {
        for (int j = 0; j < COLUMN; j++) {
            switch (map_copy[i][j]) {
            case WALL: {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(WALL_PATH)); // 绘制墙
                break;
            }
            case FLOOR: {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(FLOOR_PATH)); // 绘制空地
                break;
            }
            case DES: {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(DES_PATH)); // 绘制目的地
                break;
            }
            case MAN: {
                if(condition==1){
                                    painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(BENG)); // 绘制人
                                    man.x = i; // 记录小人位置
                                    man.y = j;
                                    break;
                                }
                else if(!ji){
                    painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(MAN_PATH)); // 绘制人
                    man.x = i; // 记录小人位置
                    man.y = j;
                    break;
                }
                else{
                    painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(JI)); // 绘制人
                    man.x = i; // 记录小人位置
                    man.y = j;
                    break;
                }

            }
            case BOX: {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(BOX_PATH)); // 绘制箱子
                break;
            }
            case HIT: {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(BOX_1_PATH));
                break;
            }
            case atk:
            {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(ATK));
                break;
            }
            case hand:
            {
                painter.drawPixmap(X_SHIFT + SIZE * j, Y_SHIFT + SIZE * i, SIZE, SIZE, QPixmap(HAND));
                break;
            }
            default:
                break;
            }
        }
    }
    //游戏寄掉时候打印寄掉，成功时打印成功
    if (isOver()) {
        emit gamesuccess();
        emit change();
    }
    //到时候考虑用这一块的思路实现变身效果，然后去掉失败的判定
    if (step > MAX_STEP) {
        emit gameover();
    }
}
//键盘控制
void game::keyPressEvent(QKeyEvent *event) {
    if(ji&&event->key() == Qt::Key_J){
                gameControl(ATTACK);
                return;
    }
    if(event->key() == Qt::Key_K){
      if(chouxiang) {
          chouxiang =0;
          condition=0;
          emit change();
      }
      else{
          chouxiang=1;
          condition=1;
          emit change();
      }
       return;
    }
    if(!over){
        if (event->key() == Qt::Key_W) {
            gameControl(UP);
        } else if (event->key() == Qt::Key_A) {
            gameControl(LEFT);
        } else if (event->key() == Qt::Key_D) {
            gameControl(RIGHT);
        } else if (event->key() == Qt::Key_S) {
            gameControl(DOWN);
        } else if (event->key() == Qt::Key_Enter) {

        }
        else {

        }
    }else{
        if (event->key() == Qt::Key_R) {
            init();
        } else{
           this-> close();
        }
    }


}
void game::gameOverControl() {
    if(!chouxiang){
        over=1;
        condition=4;
        emit change();
        QPainter painter(this);
        QFont font("黑体", 30, QFont::ExtraLight, false);
        QPen pen;
        pen.setColor(Qt::white);
        painter.setPen(pen);
        painter.setFont(font);
        painter.drawPixmap(X_SHIFT + SIZE * man.y, Y_SHIFT + SIZE * man.x, SIZE, SIZE, QPixmap(MAN_LOSE));
        painter.drawText((this->width()/2)-90 , this->height()/2-20, QString("寄！"));
        painter.drawText((this->width()/2)-280 , this->height()/2+30, QString("按R重新开始，按任意键回到选关界面"));

    }else{
        ji=1;
        condition=2;
        emit change();
    }

}

void game::gameSuccessControl() {
    over=1;
    condition=3;

    QPainter painter(this);
    QFont font("黑体", 30, QFont::ExtraLight, false);
    QPen pen;
    pen.setColor(Qt::white);
    painter.setPen(pen);
    painter.setFont(font);
    painter.drawPixmap(X_SHIFT + SIZE * man.y, Y_SHIFT + SIZE * man.x, SIZE, SIZE, QPixmap(MAN_WIN));
    painter.drawText((this->width()/2)-90 , this->height()/2-20, QString("任务成功！"));
    painter.drawText((this->width()/2)-280 , this->height()/2+30, QString("按R重新开始，按任意键回到选关界面"));
    painter.drawPixmap(0, SCREEN_HEIGHT-150, 150, 150, QPixmap(MAN_WIN)); // 绘制状态
    painter.drawText(200,SCREEN_HEIGHT-75 , QString("当前状态：赢"));//状态显示

}

